﻿using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cngot.Extensions.EventBus.RabbitMQ.Integration
{
    public class RabbitProducer : RabbitBase
    {
        public RabbitProducer(params string[] hostAndPorts) : base(hostAndPorts)
        {

        }

        #region 普通模式、Work模式
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="queue"></param>
        /// <param name="message"></param>
        /// <param name="options"></param>
        /// <param name="messageOptions"></param>
        public Task PublishAsync(string queue, string message, QueueOptions options = null, MessageOptions messageOptions = null)
        {
            return PublishAsync(queue, new string[] { message }, options, messageOptions);
        }
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="queue"></param>
        /// <param name="messages"></param>
        /// <param name="options"></param>
        /// <param name="messageOptions"></param>
        public async Task PublishAsync(string queue, string[] messages, QueueOptions options = null, MessageOptions messageOptions = null)
        {
            if (string.IsNullOrEmpty(queue))
            {
                throw new ArgumentException("queue cannot be empty", nameof(queue));
            }

            options = options ?? new QueueOptions();
            var channel = await GetChannel();
            //await PrepareQueueChannel(channel, queue, options);


            foreach (var message in messages)
            {
                var buffer = Encoding.UTF8.GetBytes(message);
                //await channel.BasicPublishAsync(
                //    exchange: "",
                //    routingKey: queue,
                //    mandatory: false,
                //    basicProperties: CreateBasicProperties(messageOptions),
                //    body: buffer
                //);

                await channel.BasicPublishAsync("", queue, true, CreateBasicProperties(messageOptions), buffer);
            }
            await channel.CloseAsync();
        }


        #endregion
        #region 订阅模式、路由模式、Topic模式
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="exchange"></param>
        /// <param name="routingKey"></param>
        /// <param name="message"></param>
        /// <param name="options"></param>
        /// <param name="messageOptions"></param>
        public void PublishAsync(string exchange, string routingKey, string message, MessageOptions messageOptions = null)
        {
            PublishAsync(exchange, new RouteMessage() { Message = message, RoutingKey = routingKey }, messageOptions);
        }
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="exchange"></param>
        /// <param name="routingKey"></param>
        /// <param name="messages"></param>
        /// <param name="options"></param>
        /// <param name="messageOptions"></param>
        public Task PublishAsync(string exchange, string routingKey, string[] messages, MessageOptions messageOptions = null)
        {
            return PublishAsync(exchange, messages.Select(message => new RouteMessage() { Message = message, RoutingKey = routingKey }).ToArray(), messageOptions);
        }
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="exchange"></param>
        /// <param name="routeMessage"></param>
        /// <param name="options"></param>
        /// <param name="messageOptions"></param>
        public Task PublishAsync(string exchange, RouteMessage routeMessage, MessageOptions messageOptions = null)
        {
            return PublishAsync(exchange, new RouteMessage[] { routeMessage }, messageOptions);
        }
        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="exchange"></param>
        /// <param name="routeMessages"></param>
        /// <param name="options"></param>
        /// <param name="messageOptions"></param>
        public async Task PublishAsync(string exchange, RouteMessage[] routeMessages,  MessageOptions messageOptions = null)
        {
            if (string.IsNullOrEmpty(exchange))
            {
                throw new ArgumentException("exchange cannot be empty", nameof(exchange));
            }

            using var channel = await GetChannel();

            foreach (var routeMessage in routeMessages)
            {
                var buffer = Encoding.UTF8.GetBytes(routeMessage.Message);

                await channel.BasicPublishAsync(exchange, routeMessage.RoutingKey, true, CreateBasicProperties(messageOptions), buffer);
            }
            await channel.CloseAsync();
            await channel.DisposeAsync();
        }
        #endregion

        public static RabbitProducer Create(RabbitBaseOptions rabbitBaseOptions)
        {
            var producer = new RabbitProducer(rabbitBaseOptions.Hosts);
            producer.Password = rabbitBaseOptions.Password;
            producer.Port = rabbitBaseOptions.Port;
            producer.UserName = rabbitBaseOptions.UserName;
            producer.VirtualHost = rabbitBaseOptions.VirtualHost;
            return producer;
        }
        public void Dispose()
        {
            //base.Dispose();
            Close().Wait();
        }
    }
    public class RouteMessage
    {
        /// <summary>
        /// 路由
        /// </summary>
        public string RoutingKey { get; set; }
        /// <summary>
        /// 消息
        /// </summary>
        public string Message { get; set; }
    }
}
